package yagwl.client.view.demo;

import java.util.logging.Logger;

import yagwl.client.model.ItemDTO;
import yagwl.client.model.demo.CatalogRpcService;
import yagwl.client.model.demo.CatalogRpcServiceAsync;
import yagwl.client.model.fnd.RpcStatus;
import yagwl.client.widget.AbstractItemDetail;
import yagwl.client.widget.FormFieldGroup;
import yagwl.client.widget.FormPanel;
import yagwl.client.widget.FormPanel.SaveButtonClickCallback;
import yagwl.client.widget.InputTextArea;
import yagwl.client.widget.InputTextBox;
import yagwl.client.widget.InputTextBox.DataType;
import yagwl.client.widget.Section;

import com.google.gwt.core.client.GWT;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.History;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;

public class ProductEditForm extends AbstractItemDetail {

  private static final Logger log = Logger.getLogger(ProductEditForm.class
      .getName());
  public final static String HistoryToken = "productEdit";

  private final Section rootSP = new Section("Create Product");
  private FormPanel rootFP = new FormPanel();
  private InputTextBox nameTB = new InputTextBox(DataType.Any, 200, "800px");
  private InputTextArea descTA = new InputTextArea().setInitialLines(2)
      .setLineIncrements(2).setTextAreaWidth("800px").setMaxCharacters(500);

  private InputTextBox imgTB = new InputTextBox(DataType.Any, 200, "800px");
  private InputTextBox priceTB = new InputTextBox(DataType.Decimal, 8);
  private InputTextArea[] fieldTA = new InputTextArea[6];

  public ProductEditForm() {
    drawForm();
    rootSP.setContent(rootFP);
    initWidget(rootSP);

    History.addValueChangeHandler(new ValueChangeHandler<String>() {
      public void onValueChange(ValueChangeEvent<String> event) {
        String historyToken = event.getValue();
        if (!historyToken.startsWith(HistoryToken))
          return;
        log.info("ProductEditForm: ValueChangeHandler caught: " + historyToken);
        String[] tokens = historyToken.split("/", 2);
        if (tokens.length < 2) {
          nullifyFields();
        } else {
          setItemId(tokens[1]);
          ItemDTO itemDTO = ProductEditForm.super.getItemDTO();
          // TODO P2 if prd == null, fetch from database
          nameTB.setValue(itemDTO.get("name"));
          descTA.setText(itemDTO.get("description"));
          imgTB.setValue(itemDTO.get("imageUrl"));
          priceTB.setValue(itemDTO.get("priceStr"));
          for (int i = 0; i < fieldTA.length; i++)
            fieldTA[i].setText(itemDTO.get("field" + (i + 1)));
          rootSP.setHeader("Update Product");
        }
      }
    });
  }

  private void drawForm() {
    rootFP.setLabelColumnWidth("120px").setDataColumnWidth("100px");
    // TODO P4 optimize flexfield input
    FormFieldGroup group = new FormFieldGroup();
    group.addField("Name", nameTB, true);
    group.addField("Description", descTA);
    group.addField("Image URL", imgTB);
    group.addField("Price", priceTB, true);
    for (int i = 0; i < fieldTA.length; i++) {
      fieldTA[i] = new InputTextArea().setInitialLines(2).setLineIncrements(4)
          .setTextAreaWidth("800px").setMaxCharacters(500);

      group.addField("Field " + (i + 1), fieldTA[i], false);
    }
    rootFP.addFieldGroup(group);

    rootFP.addSaveButton("Submit", new SubmitButtonClickCallback());
    rootFP.addBackButton("Cancel");
    rootFP.renderUI();
  }

  public class SubmitButtonClickCallback implements SaveButtonClickCallback {
    @Override
    public void save() {
      rootFP.setBusy(true);
      final ItemDTO itemDTO = new ItemDTO();
      itemDTO.put("name", nameTB.getValue());
      itemDTO.put("description", descTA.getText());
      itemDTO.put("imageUrl", imgTB.getValue());
      itemDTO.put("priceStr", priceTB.getValue());
      for (int i = 0; i < fieldTA.length; i++)
        itemDTO.put("field" + (i + 1), fieldTA[i].getText());
      CatalogRpcServiceAsync productService = GWT
          .create(CatalogRpcService.class);
      if (getItemId() != null) {
        itemDTO.setId(getItemId());
        productService.updateProduct(itemDTO, new AsyncCallback<RpcStatus>() {

          @Override
          public void onFailure(Throwable caught) {
            Window.alert(caught.toString());
          }

          @Override
          public void onSuccess(RpcStatus result) {
            if (result.getErrorCode() != null) {
              rootFP.setErrorMessage(result.getMessage());
              return;
            }
            ItemDTO prdOrig = ProductEditForm.super.getItemDTO();
            // TODO P2 handle if prdOrig = null (possible when not in cache)
            prdOrig.getMap().putAll(itemDTO.getMap());
            rootFP.setMessage("Product updated!");
            History.back();
          }
        });
      } else {
        productService.createProduct(itemDTO, new AsyncCallback<RpcStatus>() {

          @Override
          public void onFailure(Throwable caught) {
            rootFP.setErrorMessage(caught.toString());
          }

          @Override
          public void onSuccess(RpcStatus result) {
            if (result.getErrorCode() != null) {
              rootFP.setErrorMessage(result.getMessage());
              return;
            }
            rootFP.setMessage("Product created! "
                + "Create another or click Cancel to go back.");
            nullifyFields();
            if (getListCache() != null) {
              itemDTO.setId(result.getObjectId());
              getListCache().addItem(itemDTO);
            }
          }
        });
      }
    }
  }

  private void nullifyFields() {
    nameTB.setValue(null);
    descTA.clear();
    imgTB.setValue(null);
    priceTB.setValue(null);
    for (int i = 0; i < fieldTA.length; i++)
      fieldTA[i].clear();
    setItemId(null);
  }

}
